#include <iostream>
using namespace std;

const int N = 10;
int path[N];
int n;
bool st[N];    //用于记录数字是否使用过
void dfs(int u){
    //边界情况：到最底层时，依次出栈空间
    //但由于此时i <= 0，继续循环递归
    if(u == n){
        for(int i = 0; i < n; i++){
            printf("%d ", path[i]);
        }
        puts("");
        cout << endl;
        return;
    }
    //递归调用
    //此处i变量相当于根节点元素，保证所有的根节点的可能性
    //在根节点基础上，进行子树的递归调用
    //另外，path[]保存的是当前路径，
    //      st[]则保存了当前路径剩下可用的数字，因此每次回溯都会保证剩下的数字可能性

    for(int i = 1; i <= n; i ++){
        if(!st[i]){
            path[u] = i;
            st[i] = true;
            dfs(u + 1);
            st[i] = false;
        }
    }
}

int main(){
    cin >> n;
    dfs(0);
    return 0;
}